/*
Description : Gtk interface to control and monitor a relayduino board
			  (like kta223) thru its FTDI usb/serial adapter.
Author      : Samuel Ventura <samuel.ventura@yeico.com>
Copyright   : (c) 2011 Samuel Ventura. All rights reserved.
License 	: http://www.opensource.org/licenses/Apache-2.0
*/

using GLib;

namespace relayduino.gtk {

	private int fd;
	private Kta223 kta;
	private string[] baudrates;

	private Gtk.Window window;

	private Gtk.ComboBox combobox_serial_device;
	private Gtk.ComboBox combobox_serial_baudrate;
	private Gtk.Button button_serial_open;
	private Gtk.Button button_serial_close;
	private Gtk.SpinButton spinbutton_serial_address;

	private Gtk.Entry entry_socket_ip;
	private Gtk.Entry entry_socket_port;
	private Gtk.SpinButton spinbutton_socket_address;
	private Gtk.Button button_socket_open;
	private Gtk.Button button_socket_close;

	private Gtk.SpinButton spinbutton_change_address;
	private Gtk.Button button_change_address;
	private Gtk.Label label_di1;
	private Gtk.Label label_di2;
	private Gtk.Label label_di3;
	private Gtk.Label label_di4;
	private Gtk.Button button_do1;
	private Gtk.Button button_do2;
	private Gtk.Button button_do3;
	private Gtk.Button button_do4;
	private Gtk.Button button_do5;
	private Gtk.Button button_do6;
	private Gtk.Button button_do7;
	private Gtk.Button button_do8;
	private Gtk.Button button_do_on;
	private Gtk.Button button_do_off;
	private Gtk.ProgressBar progressbar_ai1;
	private Gtk.ProgressBar progressbar_ai2;
	private Gtk.ProgressBar progressbar_ai3;
	private Gtk.Label label_do1;
	private Gtk.Label label_do2;
	private Gtk.Label label_do3;
	private Gtk.Label label_do4;
	private Gtk.Label label_do5;
	private Gtk.Label label_do6;
	private Gtk.Label label_do7;
	private Gtk.Label label_do8;
	private Gtk.Label label_do_on;
	private Gtk.Label label_do_off;
	private Gtk.Label status;

	public void serial_open() {
		stdout.printf("relayduino_gtk_serial_open\n");

		Gtk.TreeIter iter;
		GLib.Value val;
		var device_model = combobox_serial_device.get_model() as Gtk.TreeModel;
		if (!combobox_serial_device.get_active_iter(out iter)) {
			on_error("No device selected");
			return;
		}
		device_model.get_value(iter, 0, out val);
		string device_name = val.get_string();
		if (device_name == null) {
			on_error("No device selected");
			return;
		}

		var baudrate_model = combobox_serial_baudrate.get_model() as Gtk.TreeModel;
		if (!combobox_serial_baudrate.get_active_iter(out iter)) {
			on_error("No baudrate selected");
			return;
		}
		baudrate_model.get_value(iter, 0, out val);
		string baudrate = val.get_string();
		if (baudrate == null) {
			on_error("No baudrate selected");
			return;
		}

		fd = Posix.open(device_name, Posix.O_RDWR | Posix.O_NOCTTY);
		if (fd < 0) {
			on_error("Unable to open device '%s'\n".printf(device_name));
			return;
		}
		if (!Posix.isatty(fd)) {
			on_error("Device is not a tty '%s'\n".printf(device_name));
			return;
		}

		if (!(baudrate in baudrates)) {
			on_error("Invalid baudrate '%s'\n".printf(baudrate));
			return;
		}

		kta = new Kta223.serial(fd, int.parse(baudrate), (int)spinbutton_serial_address.get_value(), false);
		if (kta.setup_serial() < 0) {
			on_error("Unable to setup kta\n");
			Posix.close(fd);
			return;
		}

		combobox_serial_device.set_sensitive(false);
		combobox_serial_baudrate.set_sensitive(false);
		button_serial_open.set_sensitive(false);
		button_serial_close.set_sensitive(true);
		spinbutton_serial_address.set_sensitive(false);

		entry_socket_ip.set_sensitive(false);
		entry_socket_port.set_sensitive(false);
		spinbutton_socket_address.set_sensitive(false);
		button_socket_open.set_sensitive(false);
		button_socket_close.set_sensitive(false);

		spinbutton_change_address.set_sensitive(true);
		button_change_address.set_sensitive(true);
		button_do1.set_sensitive(true);
		button_do2.set_sensitive(true);
		button_do3.set_sensitive(true);
		button_do4.set_sensitive(true);
		button_do5.set_sensitive(true);
		button_do6.set_sensitive(true);
		button_do7.set_sensitive(true);
		button_do8.set_sensitive(true);
		button_do_on.set_sensitive(true);
		button_do_off.set_sensitive(true);
	}

	public void serial_close() {
		stdout.printf("relayduino_gtk_serial_close\n");

		kta.restore_serial();
		kta = null;

		combobox_serial_device.set_sensitive(true);
		combobox_serial_baudrate.set_sensitive(true);
		button_serial_open.set_sensitive(true);
		button_serial_close.set_sensitive(false);
		spinbutton_serial_address.set_sensitive(true);

		entry_socket_ip.set_sensitive(true);
		entry_socket_port.set_sensitive(true);
		spinbutton_socket_address.set_sensitive(true);
		button_socket_open.set_sensitive(true);
		button_socket_close.set_sensitive(false);

		spinbutton_change_address.set_sensitive(false);
		button_change_address.set_sensitive(false);
		label_di1.set_markup("1 <span foreground='gray'>OFF</span>");
		label_di2.set_markup("2 <span foreground='gray'>OFF</span>");
		label_di3.set_markup("3 <span foreground='gray'>OFF</span>");
		label_di4.set_markup("4 <span foreground='gray'>OFF</span>");
		button_do1.set_sensitive(false);
		button_do2.set_sensitive(false);
		button_do3.set_sensitive(false);
		button_do4.set_sensitive(false);
		button_do5.set_sensitive(false);
		button_do6.set_sensitive(false);
		button_do7.set_sensitive(false);
		button_do8.set_sensitive(false);
		button_do_on.set_sensitive(false);
		button_do_off.set_sensitive(false);
		progressbar_ai1.set_fraction(0);
		progressbar_ai2.set_fraction(0);
		progressbar_ai3.set_fraction(0);
		progressbar_ai1.set_text("0");
		progressbar_ai2.set_text("0");
		progressbar_ai3.set_text("0");
		label_do1.set_text("Toggle 1");
		label_do2.set_text("Toggle 2");
		label_do3.set_text("Toggle 3");
		label_do4.set_text("Toggle 4");
		label_do5.set_text("Toggle 5");
		label_do6.set_text("Toggle 6");
		label_do7.set_text("Toggle 7");
		label_do8.set_text("Toggle 8");
		
		status.set_markup("Ready");
	}

	public void socket_open() {
		stdout.printf("relayduino_gtk_socket_open\n");

		var ip = entry_socket_ip.get_text();
		var inetaddress = Posix.inet_addr(ip);
		if (inetaddress == -1) {
			on_error("Invalid IP");
			return;
		}

		var port = entry_socket_port.get_text();
		if (int.parse(port)<=0 || int.parse(port)>65536) {
			on_error("Invalid port");
			return;
		}

		fd = Posix.socket(Posix.AF_INET, Posix.SOCK_STREAM, 0);
		if (fd == -1) {
			on_error("Cannot create socket");
			return;
		}
		stdout.printf("socket fd %d\n".printf(fd));

		var sa = Posix.SockAddrIn();
		sa.sin_family = Posix.AF_INET;
		sa.sin_port = Posix.htons((uint16)int.parse(port));
		sa.sin_addr.s_addr = inetaddress;
		if (-1 == Posix.connect(fd, sa, sizeof(Posix.SockAddrIn))) {
			on_error("Cannot connect socket");
			return;
		}

		kta = new Kta223.socket(fd, (int)spinbutton_socket_address.get_value(), true);
        if (kta.setup_socket() < 0) {
			on_error("Unable to setup kta\n");
			Posix.close(fd);
			return;
		}

		combobox_serial_device.set_sensitive(false);
		combobox_serial_baudrate.set_sensitive(false);
		button_serial_open.set_sensitive(false);
		button_serial_close.set_sensitive(false);
		spinbutton_serial_address.set_sensitive(false);

		entry_socket_ip.set_sensitive(false);
		entry_socket_port.set_sensitive(false);
		spinbutton_socket_address.set_sensitive(false);
		button_socket_open.set_sensitive(false);
		button_socket_close.set_sensitive(true);

		spinbutton_change_address.set_sensitive(true);
		button_change_address.set_sensitive(true);
		button_do1.set_sensitive(true);
		button_do2.set_sensitive(true);
		button_do3.set_sensitive(true);
		button_do4.set_sensitive(true);
		button_do5.set_sensitive(true);
		button_do6.set_sensitive(true);
		button_do7.set_sensitive(true);
		button_do8.set_sensitive(true);
		button_do_on.set_sensitive(true);
		button_do_off.set_sensitive(true);
	}

	public void socket_close() {
		stdout.printf("relayduino_gtk_socket_close\n");

		kta.restore_socket();
		kta = null;

		combobox_serial_device.set_sensitive(true);
		combobox_serial_baudrate.set_sensitive(true);
		button_serial_open.set_sensitive(true);
		button_serial_close.set_sensitive(false);
		spinbutton_serial_address.set_sensitive(true);

		entry_socket_ip.set_sensitive(true);
		entry_socket_port.set_sensitive(true);
		spinbutton_socket_address.set_sensitive(true);
		button_socket_open.set_sensitive(true);
		button_socket_close.set_sensitive(false);

		spinbutton_change_address.set_sensitive(false);
		button_change_address.set_sensitive(false);
		label_di1.set_markup("1 <span foreground='gray'>OFF</span>");
		label_di2.set_markup("2 <span foreground='gray'>OFF</span>");
		label_di3.set_markup("3 <span foreground='gray'>OFF</span>");
		label_di4.set_markup("4 <span foreground='gray'>OFF</span>");
		button_do1.set_sensitive(false);
		button_do2.set_sensitive(false);
		button_do3.set_sensitive(false);
		button_do4.set_sensitive(false);
		button_do5.set_sensitive(false);
		button_do6.set_sensitive(false);
		button_do7.set_sensitive(false);
		button_do8.set_sensitive(false);
		button_do_on.set_sensitive(false);
		button_do_off.set_sensitive(false);
		progressbar_ai1.set_fraction(0);
		progressbar_ai2.set_fraction(0);
		progressbar_ai3.set_fraction(0);
		progressbar_ai1.set_text("0");
		progressbar_ai2.set_text("0");
		progressbar_ai3.set_text("0");
		label_do1.set_text("Toggle 1");
		label_do2.set_text("Toggle 2");
		label_do3.set_text("Toggle 3");
		label_do4.set_text("Toggle 4");
		label_do5.set_text("Toggle 5");
		label_do6.set_text("Toggle 6");
		label_do7.set_text("Toggle 7");
		label_do8.set_text("Toggle 8");
		
		status.set_markup("Ready");
	}

	public void output_clicked(Gtk.Button source) {
		stdout.printf("relayduino_gtk_output_clicked\n");

		int outputs = 0;

		if (source == button_do_on) {
			outputs = 255;
		}
		if (source == button_do_off) {
			outputs = 0;
		}
		if (source == button_do1) {
			outputs = kta.doutputs ^ (1 << 0);
		}
		if (source == button_do2) {
			outputs = kta.doutputs ^ (1 << 1);
		}
		if (source == button_do3) {
			outputs = kta.doutputs ^ (1 << 2);
		}
		if (source == button_do4) {
			outputs = kta.doutputs ^ (1 << 3);
		}
		if (source == button_do5) {
			outputs = kta.doutputs ^ (1 << 4);
		}
		if (source == button_do6) {
			outputs = kta.doutputs ^ (1 << 5);
		}
		if (source == button_do7) {
			outputs = kta.doutputs ^ (1 << 6);
		}
		if (source == button_do8) {
			outputs = kta.doutputs ^ (1 << 7);
		}

		if (kta.write_doutputs(outputs) < 0) {
			stderr.printf("Failed to write_doutputs\n");
		}
	}

	public void address_change_clicked() {
		stdout.printf("relayduino_gtk_address_change_clicked\n");

		if (kta.change_address((int)spinbutton_change_address.get_value()) < 0) {
			stderr.printf("Failed to change_address\n");
		}
	}

	public void on_error(string str) {
		var dlg = new Gtk.MessageDialog (window, 
			Gtk.DialogFlags.DESTROY_WITH_PARENT | Gtk.DialogFlags.MODAL, 
			Gtk.MessageType.ERROR, 
			Gtk.ButtonsType.OK, str);
		dlg.run();
		dlg.destroy();
	}

	public bool on_idle() {
		//stdout.printf("relayduino_gtk_on_idle\n");

		if (kta == null) return true;
	
		if (kta.read_all() < 0) {
			stderr.printf("Failed to read_all\n");
			status.set_markup("<span color='red'>Communication error</span>");
			return true;
		}
		status.set_markup("<span color='green'>Communication ok</span>");

		label_di1.set_markup("1 <span foreground=" + ((kta.dinputs & 0x01) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_di2.set_markup("2 <span foreground=" + ((kta.dinputs & 0x02) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_di3.set_markup("3 <span foreground=" + ((kta.dinputs & 0x04) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_di4.set_markup("4 <span foreground=" + ((kta.dinputs & 0x08) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");		

		/* 10 bit */
		progressbar_ai1.set_fraction(kta.ainputs[0]/1023.0);
		progressbar_ai2.set_fraction(kta.ainputs[2]/1023.0);
		progressbar_ai3.set_fraction(kta.ainputs[3]/1023.0);

		progressbar_ai1.set_text(kta.ainputs[0].to_string());
		progressbar_ai2.set_text(kta.ainputs[2].to_string());
		progressbar_ai3.set_text(kta.ainputs[3].to_string());

		label_do1.set_markup("Toggle 1 <span foreground=" + ((kta.doutputs & 0x01) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_do2.set_markup("Toggle 2 <span foreground=" + ((kta.doutputs & 0x02) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_do3.set_markup("Toggle 3 <span foreground=" + ((kta.doutputs & 0x04) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_do4.set_markup("Toggle 4 <span foreground=" + ((kta.doutputs & 0x08) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_do5.set_markup("Toggle 5 <span foreground=" + ((kta.doutputs & 0x10) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_do6.set_markup("Toggle 6 <span foreground=" + ((kta.doutputs & 0x20) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_do7.set_markup("Toggle 7 <span foreground=" + ((kta.doutputs & 0x40) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");
		label_do8.set_markup("Toggle 8 <span foreground=" + ((kta.doutputs & 0x80) != 0 ? "'green'>ON":"'gray'>OFF") + "</span>");

		return true;
	}

	public string icon() {
		var fn = "relayduino.png";
		if (FileUtils.test(fn, FileTest.EXISTS)) return fn;
		fn = "/usr/share/icons/hicolor/48x48/apps/relayduino.png";
		if (FileUtils.test(fn, FileTest.EXISTS)) return fn;
		return null;
	}

    public int main(string[] args) {
		stdout.printf("main\n");
		Idle.add(on_idle);
		Gtk.init (ref args);

		/* 14400 and 28800 are supported by the board but undefined on current vala posix vapi */
		baudrates = new string[] {"1200", "2400", "4800", "9600", /*"14440",*/ "19200", /*"28800",*/ "38400", "57600", "115200"};

		try {
			if (build_ui()<0) return -1;
			window.icon = new Gdk.Pixbuf.from_file (icon());
			
			
			label_do1 = button_do1.get_child() as Gtk.Label;
			label_do2 = button_do2.get_child() as Gtk.Label;
			label_do3 = button_do3.get_child() as Gtk.Label;
			label_do4 = button_do4.get_child() as Gtk.Label;
			label_do5 = button_do5.get_child() as Gtk.Label;
			label_do6 = button_do6.get_child() as Gtk.Label;
			label_do7 = button_do7.get_child() as Gtk.Label;
			label_do8 = button_do8.get_child() as Gtk.Label;
			label_do_on = button_do_on.get_child() as Gtk.Label;
			label_do_off = button_do_off.get_child() as Gtk.Label;
			
			/* fill devices */
			Gtk.TreeIter iter1;
			var list1 = new Gtk.ListStore(1, typeof(string));
			for(int i=0;i<16;i++) {
				var fn = "/dev/ttyUSB%i".printf(i);
				if (FileUtils.test(fn, FileTest.EXISTS)) {
					list1.append(out iter1);
					list1.set(iter1, 0, fn, -1);
				}
			}
					
			for(int i=0;i<16;i++) {
				var fn = "/dev/ttyS%i".printf(i);
				if (FileUtils.test(fn, FileTest.EXISTS)) {
					list1.append(out iter1);
					list1.set(iter1, 0, fn, -1);
				}
			}
			combobox_serial_device.set_model(list1);
			combobox_serial_device.set_active(0);
			var render1 = new Gtk.CellRendererText();
			combobox_serial_device.pack_start(render1, true);
			combobox_serial_device.set_attributes(render1, "text", 0, null);
			
			/* fill baudrates */
			Gtk.TreeIter iter2;
			var list2 = new Gtk.ListStore(1, typeof(string));
			foreach(var br in baudrates) {
				list2.append(out iter2);
				list2.set(iter2, 0, br, -1);
			}
			combobox_serial_baudrate.set_model(list2);
			combobox_serial_baudrate.set_active(3);
			var render2 = new Gtk.CellRendererText();
			combobox_serial_baudrate.pack_start(render2, true);
			combobox_serial_baudrate.set_attributes(render2, "text", 0, null);

			window.destroy.connect (Gtk.main_quit);
		    window.show_all ();
		    Gtk.main ();
		} catch (Error e) {
		    stderr.printf ("Could not load UI: %s\n", e.message);
		    return 1;
		}

		return 0;
	}

	private int build_ui() {
		
		var hbox1 = new Gtk.HBox(false, 2);
		var hbox2 = new Gtk.HBox(false, 8);
		var hbox3 = new Gtk.HBox(false, 8);
		var hbox4 = new Gtk.HBox(false, 2);
		var hbox5 = new Gtk.HBox(true, 2);
		var hbox6 = new Gtk.HBox(false, 2);
		var hbox7 = new Gtk.HBox(false, 2);
		var hbox8 = new Gtk.HBox(false, 2);
		var vbox1 = new Gtk.VBox(false, 4);
		var vbox2 = new Gtk.VBox(false, 2);
		var vbox3 = new Gtk.VBox(true, 4);
		var vbox4 = new Gtk.VBox(true, 5);
		var vbox5 = new Gtk.VBox(true, 5);
		var vbox6 = new Gtk.VBox(true, 3);
		var frame1 = new Gtk.Frame(null);
		var frame2 = new Gtk.Frame(null);
		var frame3 = new Gtk.Frame(null);
		var frame4 = new Gtk.Frame(null);
		var frame5 = new Gtk.Frame(null);
		var note1 = new Gtk.Notebook();
		var label1 = new Gtk.Label("Device");
		var label2 = new Gtk.Label("Baudrate");
		var label3 = new Gtk.Label("Address");
		var label4 = new Gtk.Label("IP");
		var label5 = new Gtk.Label("Port");
		var label6 = new Gtk.Label("Address");
		var label7 = new Gtk.Label("1");
		var label8 = new Gtk.Label("2");
		var label9 = new Gtk.Label("3");
		var label10 = new Gtk.Label(null);
		var label11 = new Gtk.Label(null);
		var label12 = new Gtk.Label(null);
		var label13 = new Gtk.Label(null);
		var label14 = new Gtk.Label(null);

		window = new Gtk.Window();
		button_serial_open = new Gtk.Button.with_label("Open");		
		button_serial_close = new Gtk.Button.with_label("Close");		
		button_socket_open = new Gtk.Button.with_label("Open");		
		button_socket_close = new Gtk.Button.with_label("Close");
		combobox_serial_device = new Gtk.ComboBox();	
		combobox_serial_baudrate = new Gtk.ComboBox();	
		spinbutton_serial_address = new Gtk.SpinButton.with_range(0, 99, 1);	
		spinbutton_socket_address = new Gtk.SpinButton.with_range(0, 99, 1);
		entry_socket_ip = new Gtk.Entry();
		entry_socket_port = new Gtk.Entry();
		spinbutton_change_address = new Gtk.SpinButton.with_range(0, 99, 1);
		button_change_address = new Gtk.Button.with_label("Change");
		label_di1 = new Gtk.Label(null);
		label_di2 = new Gtk.Label(null);
		label_di3 = new Gtk.Label(null);
		label_di4 = new Gtk.Label(null);
		button_do1 = new Gtk.Button.with_label("Toggle 1");
		button_do2 = new Gtk.Button.with_label("Toggle 2");
		button_do3 = new Gtk.Button.with_label("Toggle 3");
		button_do4 = new Gtk.Button.with_label("Toggle 4");
		button_do5 = new Gtk.Button.with_label("Toggle 5");
		button_do6 = new Gtk.Button.with_label("Toggle 6");
		button_do7 = new Gtk.Button.with_label("Toggle 7");
		button_do8 = new Gtk.Button.with_label("Toggle 8");
		button_do_on = new Gtk.Button.with_label("All On");
		button_do_off = new Gtk.Button.with_label("All Off");
		progressbar_ai1 = new Gtk.ProgressBar();
		progressbar_ai2 = new Gtk.ProgressBar();
		progressbar_ai3 = new Gtk.ProgressBar();
		status = new Gtk.Label("Ready");
		
		window.title = "Relayduino GTK";
		window.set_resizable(false);
		window.window_position = Gtk.WindowPosition.CENTER;
		button_serial_close.set_sensitive(false);
		button_socket_close.set_sensitive(false);

		spinbutton_change_address.set_sensitive(false);
		button_change_address.set_sensitive(false);

		label_di1.set_markup("1 <span foreground='gray'>OFF</span>");
		label_di2.set_markup("2 <span foreground='gray'>OFF</span>");
		label_di3.set_markup("3 <span foreground='gray'>OFF</span>");
		label_di4.set_markup("4 <span foreground='gray'>OFF</span>");
		label10.set_markup("<b>Communication Setup</b>");
		label11.set_markup("<b>Address</b>");
		label12.set_markup("<b>Digital Inputs</b>");
		label13.set_markup("<b>Digital Outputs (Relays)</b>");
		label14.set_markup("<b>Analog Inputs</b>");
		frame1.set_label_widget(label10);
		frame2.set_label_widget(label11);
		frame3.set_label_widget(label12);
		frame4.set_label_widget(label13);
		frame5.set_label_widget(label14);

		button_do1.set_sensitive(false);
		button_do2.set_sensitive(false);
		button_do3.set_sensitive(false);
		button_do4.set_sensitive(false);
		button_do5.set_sensitive(false);
		button_do6.set_sensitive(false);
		button_do7.set_sensitive(false);
		button_do8.set_sensitive(false);
		button_do_on.set_sensitive(false);
		button_do_off.set_sensitive(false);
		
		progressbar_ai1.set_text("0");
		progressbar_ai2.set_text("0");
		progressbar_ai3.set_text("0");
		
		spinbutton_serial_address.set_width_chars(5);
		spinbutton_socket_address.set_width_chars(5);
		spinbutton_change_address.set_width_chars(5);
		entry_socket_ip.set_width_chars(15);
		entry_socket_port.set_width_chars(5);
		entry_socket_ip.set_text("127.0.0.1");
		entry_socket_port.set_text("4001");

		status.set_alignment(0f, 0.5f);

		button_serial_open.clicked.connect(serial_open);		
		button_serial_close.clicked.connect(serial_close);
		button_socket_open.clicked.connect(socket_open);		
		button_socket_close.clicked.connect(socket_close);
		button_change_address.clicked.connect(address_change_clicked);
		button_do1.clicked.connect(output_clicked);
		button_do2.clicked.connect(output_clicked);
		button_do3.clicked.connect(output_clicked);
		button_do4.clicked.connect(output_clicked);
		button_do5.clicked.connect(output_clicked);
		button_do6.clicked.connect(output_clicked);
		button_do7.clicked.connect(output_clicked);
		button_do8.clicked.connect(output_clicked);
		button_do_on.clicked.connect(output_clicked);
		button_do_off.clicked.connect(output_clicked);
		
		window.add(vbox1);
		vbox1.add(frame1);
			frame1.add(note1);
				note1.append_page(hbox2, new Gtk.Label("Serial Port"));
					hbox2.add(label1);
					hbox2.add(combobox_serial_device);
					hbox2.add(label2);
					hbox2.add(combobox_serial_baudrate);
					hbox2.add(label3);
					hbox2.add(spinbutton_serial_address);
					hbox2.add(button_serial_open);
					hbox2.add(button_serial_close);
				note1.append_page(hbox3, new Gtk.Label("Socket"));
					hbox3.add(label4);
					hbox3.add(entry_socket_ip);
					hbox3.add(label5);
					hbox3.add(entry_socket_port);
					hbox3.add(label6);
					hbox3.add(spinbutton_socket_address);
					hbox3.add(button_socket_open);
					hbox3.add(button_socket_close);
		vbox1.add(hbox1);
			hbox1.pack_start(vbox2, false);
				vbox2.pack_start(frame2, false);
					frame2.add(hbox4);
						hbox4.add(spinbutton_change_address);
						hbox4.add(button_change_address);
				vbox2.add(frame3);
					frame3.add(vbox3);
						vbox3.add(label_di1);
						vbox3.add(label_di2);
						vbox3.add(label_di3);
						vbox3.add(label_di4);
			hbox1.add(frame4);
				frame4.add(hbox5);
					hbox5.add(vbox4);
						vbox4.add(button_do1);
						vbox4.add(button_do2);
						vbox4.add(button_do3);
						vbox4.add(button_do4);
						vbox4.add(button_do_on);
					hbox5.add(vbox5);
						vbox5.add(button_do5);
						vbox5.add(button_do6);
						vbox5.add(button_do7);
						vbox5.add(button_do8);
						vbox5.add(button_do_off);
		vbox1.add(frame5);
			frame5.add(vbox6);
				vbox6.add(hbox6);
					hbox6.pack_start(label7, false);
					hbox6.add(progressbar_ai1);
				vbox6.add(hbox7);
					hbox7.pack_start(label8, false);
					hbox7.add(progressbar_ai2);
				vbox6.add(hbox8);
					hbox8.pack_start(label9, false);
					hbox8.add(progressbar_ai3);
		vbox1.add(status);
		
		return 0;
	}
}
